﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Sinacor.Infra.Common.Security.Cryptography;
using Sinacor.Infra.Core.Licensing;

namespace Sinacor.Infra.Core.Licensing
{
    [Serializable]
    public class LicensingValidator
    {
        bool _isValid = true;
		SignedLicensing _signedLicensing;

		public bool IsValid
		{
			get { return _isValid; }
		}

        public LicensingValidator()
        {
        }

        public LicensingValidator(SignedLicensing signedLicensing)
        {
            LoadSignedLicensing(signedLicensing);
        }
        
        public SignedLicensing SignedLicensing
        {
            get { return _signedLicensing; }
            set
            {
                LoadSignedLicensing(value);
            }
        }

        void LoadSignedLicensing(SignedLicensing signedLicensing)
        {
            byte[] message = signedLicensing.DencryptedLicensing;
            byte[] key = signedLicensing.PublicKey;
            byte[] signature = signedLicensing.Signature;

            _signedLicensing = signedLicensing;

            if (signedLicensing != null)
            {
                if (!DsaSigner.VerifySignature(message, key, signature))
                {
                    _isValid = false;
                    throw new LicensingCorruptedException("Licensing File is corrupted.");
                }
            }
            else
            {
                _isValid = false;
                throw new ArgumentNullException("SignedLicensing");
            }
        }

        public bool Validate(Company company, Module module)
        {
            bool result = false;

            if (_signedLicensing != null)
            {
                if (IsValid)
                {
                    if (SignedLicensing.Licensing.Treaty == Treaty.Trial)
                        result = (SignedLicensing.Licensing.GoodThru.Value >= DateTime.Now);
                    else if (Validate(company))
                    {
                        //Company c = SignedLicensing.Licensing.Companies.Find(m => m.LegalRegistrationId == company.LegalRegistrationId && m.Name == company.Name && m.SinacorCompanyId == company.CompanyId);
                        Company c = SignedLicensing.Licensing.Companies.Find(m => m.LegalRegistrationId == company.LegalRegistrationId);                        

                        if (c != null)
                        {
                            foreach (Module m in c.Modules)
                            {
                                if (module.Monogram.Trim().ToUpper() == m.Monogram.Trim().ToUpper() &&
                                    ((module.Plus && module.Plus == m.Plus) || !module.Plus))
                                {
                                    //TODO: Fazer um controle melhor da data de validade.
                                    //Gravar data do último acesso e se ela for menor que hoje, também é inválido.
                                    if (m.GoodThru >= DateTime.Now)
                                    {
                                        result = true;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else
                throw new ArgumentNullException("SignedLicensing");

            return result;
        }        

        public bool Validate(Company company)
        {
            bool result = false;

            if (_signedLicensing != null)
            {
                if (IsValid)
                {
                    if (SignedLicensing.Licensing.Treaty == Treaty.Trial)
                        result = (SignedLicensing.Licensing.GoodThru.Value >= DateTime.Now);
                    else
                    {
                        foreach (Company c in SignedLicensing.Licensing.Companies)
                        {
                            //if (company.Name == c.Name && company.LegalRegistrationId == c.LegalRegistrationId && company.CompanyId == c.SinacorCompanyId)
                            if (company.LegalRegistrationId == c.LegalRegistrationId)
                            {
                                result = true;
                                break;
                            }
                        }
                    }
                }
            }
            else
                throw new ArgumentNullException("SignedLicensing");

            return result;
        }

        public bool Validate(string ownerLegalIdRegistration)
        {
            bool result = false;

            if (_signedLicensing != null)
            {
                if (IsValid)
                {
                    if (SignedLicensing.Licensing.OwnerLegalRegistrationId == ownerLegalIdRegistration)
                        result = true;
                }
            }
            else
                throw new ArgumentNullException("SignedLicensing");

            return result;
        }

        public bool ValidateLicenseTrial(out int days_remaining)
        {
            bool result = false;
            days_remaining = -1;

            if (_signedLicensing != null)
            {
                if (IsValid)
                {
                    if (SignedLicensing.Licensing.Treaty == Treaty.Trial)
                    {
                        if (SignedLicensing.Licensing.GoodThru.Value >= DateTime.Now)
                        {
                            days_remaining = SignedLicensing.Licensing.GoodThru.Value.Subtract(DateTime.Now).Days;
                            result = true;
                        }
                    }
                }
            }
            else
                throw new ArgumentNullException("SignedLicensing");

            return result;
        }
    }
}